package com.ssy.lingxi.order.serviceimpl.base;

import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.order.entity.OrderDO;
import com.ssy.lingxi.order.model.bo.ProcessStepsBO;
import com.ssy.lingxi.order.model.bo.ProcessTaskBO;
import com.ssy.lingxi.order.model.constant.OrderServiceContants;
import com.ssy.lingxi.order.model.vo.basic.response.WorkFlowStepVO;
import com.ssy.lingxi.order.service.base.IBaseOrderTaskService;
import com.ssy.lingxi.workflow.api.feign.ProcessFeign;
import com.ssy.lingxi.workflow.api.model.vo.request.ComplexProcessQueryVO;
import com.ssy.lingxi.workflow.api.model.vo.request.SerialTaskExecuteVO;
import com.ssy.lingxi.workflow.api.model.vo.request.TaskExecuteVO;
import com.ssy.lingxi.workflow.api.model.vo.request.TaskStartVO;
import com.ssy.lingxi.workflow.api.model.vo.response.ComplexTaskCompleteVO;
import com.ssy.lingxi.workflow.api.model.vo.response.ComplexTaskDefVO;
import com.ssy.lingxi.workflow.api.model.vo.response.ExternalTaskVO;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 执行订单流程相关接口实现类
 * @author 万宁
 * @version 2.0.0
 * @date 2021-08-28
 */
@Service
public class BaseOrderTaskServiceImpl implements IBaseOrderTaskService {
    @Resource
    private ProcessFeign processFeign;

    /**
     * 查询订单流程步骤
     *
     * @param processKey     流程Key
     * @param taskId         流程步骤任务Id
     * @param vendorMemberId 供应商会员Id
     * @param vendorRoleId   供应商会员角色Id
     * @param buyerRoleId    采购商会员角色Id
     * @param externalTaskName 根据外部流程节点名称（子流程名称）查询内部流程
     * @return 查询结果
     */
    @Override
    public Wrapper<ProcessStepsBO> listOrderProcessSteps(String processKey, String taskId, Long vendorMemberId, Long vendorRoleId, Long buyerRoleId, String externalTaskName) {
        ComplexProcessQueryVO queryVO = new ComplexProcessQueryVO();
        queryVO.setProcessKey(processKey);
        queryVO.setTaskId(taskId);
        queryVO.setMemberId(vendorMemberId);
        queryVO.setRoleId(vendorRoleId);
        queryVO.setSubRoleId(buyerRoleId);
        Wrapper<ComplexTaskDefVO> result = processFeign.findComplexTaskDefinitions(queryVO);
        if(result.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(result.getCode(), result.getMessage());
        }

        String pattern = "\\(\\d+\\)";

        ProcessStepsBO stepsBO = new ProcessStepsBO();
        //由于现有的工作流复杂流程定义中，当流程执行完毕（taskId为空）时，将当前步骤设置为0了；所以这里要再次判断
        stepsBO.setCurrentOuterStep(!StringUtils.hasLength(taskId) && result.getData().getCurrentOuterStep().equals(0) ? result.getData().getExternalTasks().stream().mapToInt(ExternalTaskVO::getTaskStep).max().orElse(0) : result.getData().getCurrentOuterStep());
        stepsBO.setOuterSteps(result.getData().getExternalTasks().stream().map(task -> new WorkFlowStepVO(task.getTaskStep(), task.getTaskName().replaceAll(pattern, ""), task.getMemberRoleName())).sorted(Comparator.comparingInt(WorkFlowStepVO::getStep)).collect(Collectors.toList()));
        if(StringUtils.hasLength(externalTaskName)) {
            ExternalTaskVO externalTask = result.getData().getExternalTasks().stream().filter(task -> task.getTaskName().equals(externalTaskName)).findFirst().orElse(null);
            if(externalTask != null) {
                stepsBO.setInnerSteps(externalTask.getSubTasks().stream().map(internalTask -> new WorkFlowStepVO(internalTask.getTaskStep(), internalTask.getTaskName().replaceAll(pattern, ""), internalTask.getUserRoleName())).sorted(Comparator.comparingInt(WorkFlowStepVO::getStep)).collect(Collectors.toList()));
                //判断内部流程步骤
                switch (result.getData().getCurrentOuterStep().compareTo(externalTask.getTaskStep())) {
                    case 0:
                        stepsBO.setCurrentInnerStep(result.getData().getCurrentInnerStep().equals(0) ? stepsBO.getInnerSteps().stream().map(WorkFlowStepVO::getStep).max(Comparator.comparingInt(Integer::intValue)).orElse(0) : result.getData().getCurrentInnerStep());
                        break;
                    case 1:
                        stepsBO.setCurrentInnerStep(stepsBO.getInnerSteps().stream().map(WorkFlowStepVO::getStep).max(Comparator.comparingInt(Integer::intValue)).orElse(0));
                        break;
                    default:
                        stepsBO.setCurrentInnerStep(0);
                        break;
                }
            }
        }

        return Wrapper.success(stepsBO);
    }

    /**
     * 启动订单流程
     *
     * @param order 订单
     * @return 启动结果
     */
    @Override
    public Wrapper<ProcessTaskBO> startOrderProcess(OrderDO order) {
        TaskStartVO startVO = new TaskStartVO();
        startVO.setProcessKey(order.getTask().getProcessKey());
        startVO.setMemberId(order.getBuyerMemberId());
        startVO.setRoleId(order.getBuyerRoleId());
        startVO.setDataId(order.getId());
        //这里是启动流程
        Wrapper<ComplexTaskCompleteVO> result = processFeign.startProcess(startVO);
        if(result.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(result.getCode(), result.getMessage());
        }

        ProcessTaskBO taskResult = new ProcessTaskBO(result.getData(), true);

        //订单的内、外状态，以及下一步的任务Id、支付节点信息等
        order.setBuyerInnerStatus(taskResult.getBuyerInnerStatus());
        order.setVendorInnerStatus(taskResult.getVendorInnerStatus());
        order.setOuterStatus(taskResult.getOuterStatus());
        order.getTask().setTaskId(taskResult.getTaskId());
        order.getTask().setNextPay(taskResult.getNextPay());
        order.getTask().setNextSerialNo(taskResult.getNextSerialNo());
        order.getTask().setPayStartNode(taskResult.getPayStartNode());
        order.getTask().setPayEndNode(taskResult.getPayEndNode());

        return Wrapper.success(taskResult); }

    /**
     * 启动订单流程，并执行第一个任务
     *
     * @param order 订单
     * @return 启动结果
     */
    @Override
    public Wrapper<ProcessTaskBO> startOrderProcessThenExecFirstTask(OrderDO order) {
        TaskStartVO startVO = new TaskStartVO();
        startVO.setProcessKey(order.getTask().getProcessKey());
        startVO.setMemberId(order.getBuyerMemberId());
        startVO.setRoleId(order.getBuyerRoleId());
        startVO.setDataId(order.getId());

        Wrapper<ComplexTaskCompleteVO> result = processFeign.startProcessThenCompleteFirstTask(startVO);
        if(result.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(result.getCode(), result.getMessage());
        }

        ProcessTaskBO taskResult = new ProcessTaskBO(result.getData(), false);

        //订单的内、外状态，以及下一步的任务Id、支付节点信息等
        order.setBuyerInnerStatus(taskResult.getBuyerInnerStatus());
        order.setVendorInnerStatus(taskResult.getVendorInnerStatus());
        order.setOuterStatus(taskResult.getOuterStatus());
        order.getTask().setTaskId(taskResult.getTaskId());
        order.getTask().setNextPay(taskResult.getNextPay());
        order.getTask().setNextSerialNo(taskResult.getNextSerialNo());
        order.getTask().setPayStartNode(taskResult.getPayStartNode());
        order.getTask().setPayEndNode(taskResult.getPayEndNode());

        return Wrapper.success(taskResult);
    }

    /**
     * 执行订单流程
     *
     * @param order 订单
     * @return 执行结果
     */
    @Override
    public Wrapper<ProcessTaskBO> execOrderProcess(OrderDO order) {
        return execOrderProcess(order, OrderServiceContants.DIRECT_EXEC_TASK);
    }

    /**
     * 执行订单流程
     *
     * @param order 订单
     * @param agree 流程图定义的跳转参数
     * @return 执行结果
     */
    @Override
    public Wrapper<ProcessTaskBO> execOrderProcess(OrderDO order, Integer agree) {
        TaskExecuteVO executeVO = new TaskExecuteVO();
        executeVO.setProcessKey(order.getTask().getProcessKey());
        executeVO.setTaskId(order.getTask().getTaskId());
        executeVO.setMemberId(order.getBuyerMemberId());
        executeVO.setRoleId(order.getBuyerRoleId());
        executeVO.setDataId(order.getId());
        executeVO.setAgree(agree == null ? -1 : agree);

        Wrapper<ComplexTaskCompleteVO> result = processFeign.completeTask(executeVO);
        if(result.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(result.getCode(), result.getMessage());
        }

        ProcessTaskBO taskResult = new ProcessTaskBO(result.getData(), false);

        //订单的内、外状态，以及下一步的任务Id、支付节点信息等
        order.setBuyerInnerStatus(taskResult.getBuyerInnerStatus());
        order.setVendorInnerStatus(taskResult.getVendorInnerStatus());
        order.setOuterStatus(taskResult.getOuterStatus());
        order.getTask().setTaskId(taskResult.getTaskId());
        order.getTask().setNextPay(taskResult.getNextPay());
        order.getTask().setNextSerialNo(taskResult.getNextSerialNo());
        order.getTask().setPayStartNode(taskResult.getPayStartNode());
        order.getTask().setPayEndNode(taskResult.getPayEndNode());

        return Wrapper.success(taskResult);
    }

    /**
     * 连续执行支付流程
     *
     * @param order         订单
     * @param execTimes     执行次数
     * @param agrees        跳转参数列表
     * @return 执行结果
     */
    @Override
    public Wrapper<ProcessTaskBO> execOrderPayTasks(OrderDO order, Integer execTimes, List<Integer> agrees) {
        SerialTaskExecuteVO executeVO = new SerialTaskExecuteVO();
        executeVO.setProcessKey(order.getTask().getProcessKey());
        executeVO.setMemberId(order.getBuyerMemberId());
        executeVO.setRoleId(order.getBuyerRoleId());
        executeVO.setDataId(order.getId());
        executeVO.setTaskId(order.getTask().getTaskId());
        executeVO.setExecTimes(execTimes);
        executeVO.setAgrees(agrees);

        Wrapper<ComplexTaskCompleteVO> result = processFeign.completeSerialTasks(executeVO);
        if(result.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(result.getCode(), result.getMessage());
        }

        ProcessTaskBO taskResult = new ProcessTaskBO(result.getData(), false);

        //订单的内、外状态，以及下一步的任务Id、支付节点信息等
        order.setBuyerInnerStatus(taskResult.getBuyerInnerStatus());
        order.setVendorInnerStatus(taskResult.getVendorInnerStatus());
        order.setOuterStatus(taskResult.getOuterStatus());
        order.getTask().setTaskId(taskResult.getTaskId());
        order.getTask().setNextPay(taskResult.getNextPay());
        order.getTask().setNextSerialNo(taskResult.getNextSerialNo());
        order.getTask().setPayStartNode(taskResult.getPayStartNode());
        order.getTask().setPayEndNode(taskResult.getPayEndNode());

        return Wrapper.success(taskResult);
    }
}
